home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
GameWare Collection
/
GameWare Collection (CMS Software) (1993).iso
/
games
/
s_games
/
spaceinv.pas
< prev
next >
Wrap
Pascal/Delphi Source File
|
1990-09-29
|
16KB
|
580 lines
{$C-}
PROGRAM SpaceInv;
{
VERSION 5.1 -- By Timothy Campbell
}
TYPE
Line = STRING[80];
Sprite = STRING[7];
SpriteType = (Base,Missle,Ufo1,Bomb1,Ufo2,Bomb2,Ufo3,Bomb3,Ufo4,Bomb4,
Ufo5,Bomb5,Ufo6,Bomb6);
Switch = (Off,On);
CONST
Blanks = ' ';
DelayAdj = 3;
DelayInit = 70;
NumSyms = 13;
Shields = ' '#176#177#178#219;
Sprites : ARRAY [0..NumSyms] OF Sprite =
( #213#209#202#209#184,
#024,
#017#016#174#153#175#017#016,
#079,
#060#243#234#242#062,
#147,
#174#017#016#175,
#015,
#017#001#016,
#157,
#199#002#182,
#031,
#233,
'v' );
Explode : ARRAY [0..5] OF Sprite =
( #219#219#219#219#219#219#219,
#178#178#178#178#178#178#178,
#177#177#177#177#177#177#177,
#176#176#176#176#176#176#176,
'- - - - -',
' ' );
VAR
Active : ARRAY[0..NumSyms] OF BOOLEAN;
ActiveCnt : BYTE;
Beat : INTEGER;
BombType : SpriteType;
DelayTime : INTEGER;
Explosion : BYTE;
InChar : CHAR;
MisX : BYTE;
MisY : BYTE;
Move : ARRAY[0..NumSyms] OF INTEGER;
MoveUfo6 : BYTE;
Noise : BOOLEAN;
NowX : BYTE;
NowY : BYTE;
ShieldLev : BYTE;
RandomMod : BYTE;
Score : INTEGER;
ShieldCnt : INTEGER;
SpriteLen : BYTE;
SprX : BYTE;
SprY : BYTE;
Thingy : INTEGER;
Tick : BYTE;
UfoTick : BYTE;
UfoType : SpriteType;
WX,WY : BYTE;
XPosn : ARRAY[0..NumSyms] OF BYTE;
YPosn : ARRAY[0..NumSyms] OF BYTE;
FUNCTION Divis(Dv1,Dv2 : INTEGER) : BOOLEAN;
BEGIN
IF (Dv1 DIV Dv2) * Dv2 = Dv1
THEN Divis := TRUE
ELSE Divis := FALSE;
END;
PROCEDURE Ce(CIn : Line);
BEGIN
GOTOXY(((80 - LENGTH(Cin)) DIV 2),WHEREY);
WRITELN(CIn);
END;
FUNCTION Sz(SIn : Line) : Line;
BEGIN
Sz := Copy((SIn + Blanks),1,7);
END;
PROCEDURE DawdleJet;
VAR
BanLoop : BYTE;
Mult : INTEGER;
BEGIN
Mult := 1;
Thingy := 100;
REPEAT
Thingy := Thingy + Mult;
IF Thingy > 4000 THEN Mult := -1;
IF Thingy < 100 THEN Mult := 1;
FOR BanLoop := 1 TO 5 DO
BEGIN
SOUND(Thingy);
DELAY(1);
SOUND(4200-Thingy);
DELAY(1+RANDOM(8));
END;
UNTIL KEYPRESSED;
READ(KBD,InChar);
NOSOUND;
END;
PROCEDURE DawdleNoise;
BEGIN
REPEAT
SOUND(200+RANDOM(3000));
DELAY(1+RANDOM(8));
NOSOUND;
DELAY(1+RANDOM(50));
UNTIL KEYPRESSED;
READ(KBD,InChar);
NOSOUND;
END;
PROCEDURE Banner;
BEGIN
CLRSCR;
Ce('┌───────────────────────────────────────────────────────┬──────────────────┐');
Ce('│ Pinnacle Software''s Space Investors Video Game │ SPACEINV │');
Ce('├───────────────────────────────────────────────────────┴──────────────────┤');
Ce('│ C O P Y R I G H T (C) 1986 BY P I N N A C L E S O F T W A R E │');
Ce('├──────────────────────────────────────────────────────────────────────────┤');
Ce('│ This program may be freely distributed so long as it is distributed in │');
Ce('│ its complete and unaltered form, including this notice. │');
Ce('├──────────────────────────────────────────────────────────────────────────┤');
Ce('├──────────── ╦══╗ ═╦═ ╦═╗ ╔ ╦═╗ ╔ ╔══╗ ╔══╗ ╦ ╦══╗ ────────────┤');
Ce('├──────────── ╠══╝ ║ ║ ║ ║ ║ ║ ║ ╠══╣ ║ ║ ╠═ ────────────┤');
Ce('├──────────── ╩ ═╩═ ╝ ╚═╝ ╝ ╚═╝ ╩ ╩ ╚══╝ ╩══╝ ╩══╝ ────────────┤');
Ce('├──────────── ╔══╗ ╔══╗ ╦══╗ ╔═╦═╗ ╗ ╔ ╔═╗ ╦══╗ ╦══╗ ────────────┤');
Ce('├──────────── ╚══╗ ║ ║ ╠═ ║ ║ ║ ║ ╠═╣ ╠═╦╝ ╠═ ────────────┤');
Ce('├──────────── ╚══╝ ╚══╝ ╩ ╩ ╚═╩═╝ ╩ ╩ ╩ ╚╝ ╩══╝ ────────────┤');
Ce('├──────────── Post Office Box 163 Cartierville Station ────────────┤');
Ce('├──────────── Cartierville, Quebec, Canada, H4K 2J5 ────────────┤');
Ce('└──────────────────────────────────────────────────────────────────────────┘');
WRITELN;
Ce('Want to run a new kind of BBS? Send us $35 and we''ll send you your copy of');
Ce('one of Montreal''s top BBS''s: the Pyroto Mountain BBS/Game system. You''ll');
Ce('need a 128K IBM-PC with two diskette drives and a "smart" modem. ');
WRITELN;
Ce('PRESS A KEY TO CONTINUE');
DawdleJet;
CLRSCR;
Ce('PINNACLE SOFTWARE PRESENTS');
Ce('┌─-─=─=─=─=─=─=─=─=─=─=─=─=─=─=─=─-─┐');
Ce(') S P A C E I N V E S T O R S (');
Ce('└─-─=─=─=─=─=─=─=─=─=─=─=─=─=─=─=─-─┘');
WRITELN;
Ce('Watch out for ...');
WRITELN;
Ce('THE MOTHER SHIP ' + Sz(Sprites[ORD(Ufo1)]));
Ce('THE BATTLE POD ' + Sz(' '+Sprites[ORD(Ufo2)]));
Ce('THE DRIFTER ' + Sz(' '+Sprites[ORD(Ufo3)]));
Ce('THE HARASSER ' + Sz(' '+Sprites[ORD(Ufo4)]));
Ce('THE DARE-DEVIL ' + Sz(' '+Sprites[ORD(Ufo5)]));
Ce('THE OBSERVER ' + Sz(' '+Sprites[ORD(Ufo6)]));
WRITELN;
Ce(' The keys are used as follows... ');
Ce(' F and J ..... move base left and right ');
Ce(' E and I ..... either key will stop base movement');
Ce(' Spacebar .... fires a missle ');
Ce(' - (minus) ... toggles sound on and off ');
Ce(' P ........... pauses the game ');
Ce(' ESC ......... exits the game (you coward!) ');
WRITELN;
Ce('*** PRESS A KEY TO START ***');
DawdleNoise;
END;
PROCEDURE ShowScore;
BEGIN
GOTOXY(1,25);
WRITE('SCORE: ',Score,' SHIELD LEVEL: ',
Copy(Shields,1,ShieldLev),' ');
END;
PROCEDURE Cursor(CCtl : Switch);
TYPE
regpack =
RECORD
ax,bx,cx,dx,bp,di,si,ds,es,flags: INTEGER;
END;
VAR
recpack : regpack;
BEGIN
WITH recpack DO
BEGIN
ax := $0100;
IF CCtl = On
THEN cx := $0CCD
ELSE cx := $FFFF;
END;
INTR($10,recpack);
END;
PROCEDURE BEEP(Tone : INTEGER);
BEGIN
IF Noise THEN SOUND(Tone);
END;
PROCEDURE SetPosn(IntST : SpriteType; IntX, IntY : BYTE);
BEGIN
IF ((IntX = 0) AND (IntY = 0)) AND (Active[ORD(IntST)] = TRUE) THEN
BEGIN
Active[ORD(IntST)] := FALSE;
ActiveCnt := ActiveCnt - 1;
END;
IF ((IntX > 0) AND (IntY > 0)) THEN
BEGIN
IF Active[ORD(IntST)] = FALSE THEN
BEGIN
Active[ORD(IntST)] := TRUE;
IF (RANDOM(100) < 33) AND (IntST IN [Ufo1,Ufo2,Ufo3,Ufo4,Ufo5,Ufo6]) THEN
BEGIN
Move[ORD(IntST)] := -1;
IntX := 80 - LENGTH(Sprites[ORD(IntST)]) - 1;
END
ELSE Move[ORD(IntST)] := 1;
ActiveCnt := ActiveCnt + 1;
END;
XPosn[ORD(IntST)] := IntX;
YPosn[ORD(IntST)] := IntY;
END;
END;
PROCEDURE FindXY(FndST : SpriteType);
BEGIN
NowX := XPosn[ORD(FndST)];
NowY := YPosn[ORD(FndST)];
END;
{======= MOVEMENT =======}
PROCEDURE MoveX(SprTyp : SpriteType);
VAR
OutSprite : STRING[9];
XGo : BYTE;
YGo : BYTE;
BEGIN
OutSprite := Sprites[ORD(SprTyp)];
SpriteLen := Length(OutSprite);
FindXY(SprTyp);
IF SprTyp <> Base THEN
BEGIN
IF (RANDOM(1000) < SpriteLen * 5)
OR ((SprTyp = Ufo6) AND (RANDOM(100) < 5)) THEN
BEGIN
IF NowX < XPosn[ORD(Base)] THEN Move[ORD(SprTyp)] := 1;
IF NowX > XPosn[ORD(Base)] THEN Move[ORD(SprTyp)] := -1;
END;
END;
XGo := NowX + Move[ORD(SprTyp)];
IF XGo < 1 THEN XGo := 1;
IF XGo + SpriteLen > 80 THEN XGo := 80 - SpriteLen;
SetPosn(SprTyp,XGo,NowY);
IF SprTyp <> Base THEN
BEGIN
IF RANDOM(120) < ORD(SprTyp) THEN
BEGIN
OutSprite := COPY(Blanks,1,SpriteLen);
IF RANDOM(100) < 33
THEN YGo := NowY - 1
ELSE YGo := NowY + 1;
IF YGo < 1 THEN YGo := 1;
IF YGo > 18 THEN YGo := 17;
GOTOXY(NowX,YGo);
WRITE(Sprites[ORD(SprTyp)]);
FOR Thingy := 40 DOWNTO 5 DO BEEP(Thingy * 100);
SetPosn(SprTyp,NowX,YGo);
END;
END;
IF (XGo > 1) AND (Move[ORD(SprTyp)] > 0) THEN
BEGIN
XGo := XGo - 1;
OutSprite := ' ' + OutSprite;
END;
IF (XGo < 80) AND (Move[ORD(SprTyp)] < 0) THEN OutSprite := OutSprite + ' ';
GOTOXY(XGo,NowY);
WRITE(OutSprite);
END;
PROCEDURE CheckBoom(BWep, Wnme : SpriteType; MisX, MisY : BYTE);
BEGIN
FindXY(Wnme);
SpriteLen := LENGTH(Sprites[ORD(Wnme)]);
IF (MisX IN [NowX .. (NowX + SpriteLen-1)]) AND (MisY = NowY)
AND Active[ORD(Wnme)]
THEN
BEGIN
FOR Explosion := 0 TO 5 DO
BEGIN
FOR Thingy := 1 TO (SpriteLen * 10) DO
BEGIN
DELAY(1);
BEEP(500+RANDOM(4000 - Thingy * 50));
END;
GOTOXY(NowX,NowY);
WRITE(Copy(Explode[Explosion],1,SpriteLen));
END;
IF BWep = Missle THEN
BEGIN
Score := Score + (14 - ORD(Wnme)) * 10;
SetPosn(Wnme,0,0);
SetPosn(Missle,0,0);
END
ELSE
BEGIN
IF Divis(Beat,3)
THEN Move[ORD(PRED(BWep))] := Move[ORD(PRED(Bwep))] * -1;
Score := Score - 100;
IF Score < 0 THEN Score := 0;
SetPosn(BWep,0,0);
ShieldLev := ShieldLev - 1;
END;
ShowScore;
END; { Weapon hit enemy }
END; { CheckBoom }
PROCEDURE MoveWeapon(WType : SpriteType);
BEGIN
IF Active[ORD(WType)] THEN
BEGIN
FindXY(WType);
GOTOXY(NowX,NowY);
WRITE(' ');
IF (PRED(WType) IN [Ufo1,Ufo2]) THEN
BEGIN
{-- Smart Bomb --}
IF Divis(Beat,ORD(WType)*3)
AND Active[ORD(PRED(WType))]
THEN
BEGIN
FOR Thingy := 1 TO (Score DIV 1000) DO
BEGIN
IF XPosn[ORD(Base)] > NowX THEN NowX := NowX + 1;
IF XPosn[ORD(Base)] < NowX THEN NowX := NowX - 1;
END;
END;
END;
IF WType = Missle
THEN NowY := NowY - 1
ELSE NowY := NowY + 1;
IF NOT (NowY IN [1..24])
THEN SetPosn(WType,0,0)
ELSE
BEGIN
BEEP(500+(ORD(WType)*RANDOM(200))+(25-NowY)*100);
GOTOXY(NowX,NowY);
WRITE(Sprites[ORD(WType)]);
SetPosn(WType,NowX,NowY);
WX := NowX;
WY := NowY;
IF WType = Missle
THEN
BEGIN
CheckBoom(WType,Ufo1,WX,WY);
CheckBoom(WType,Ufo2,WX,WY);
CheckBoom(WType,Ufo3,WX,WY);
CheckBoom(WType,Ufo4,WX,WY);
CheckBoom(WType,Ufo5,WX,WY);
CheckBoom(WType,Ufo6,WX,WY);
END
ELSE CheckBoom(WType,Base,WX,WY);
END; { Weapon on screen }
END; { Specified weapon active }
END;
PROCEDURE MoveUfo(UfoST : SpriteType);
BEGIN
{--- Ufo Movement ---}
IF Active[ORD(UfoST)] THEN
BEGIN
IF (Tick IN [1..7]) THEN Move[ORD(UfoST)] := Move[ORD(UfoST)] * -1;
UfoTick := UfoTick + RANDOM(3);
IF UfoTick > 99 THEN UfoTick := 0;
IF Divis(UfoTick,(ORD(UfoST) DIV 2)) THEN
BEGIN
MoveX(UfoST);
BEEP(ORD(UfoST) * 300);
DELAY(1);
SprX := NowX;
FindXY(Base);
{--- Drop a bomb? ---}
IF (NOT Active[ORD(UfoST)+1]) { Not if one already dropping }
AND
(((Beat < LENGTH(Sprites[ORD(UfoST)])*10) AND
(SprX IN [NowX-1,NowX,NowX+1])) { Bigger Ufo's use good shots }
OR
(Beat < (Score DIV 20))) { 100% chance at score 2000 }
AND (NOT ((UfoST = Ufo6) AND (RANDOM(1000) < 995))) { Rare bomber }
THEN
BEGIN
BEEP(1200);
FindXY(UfoST);
SetPosn(SUCC(UfoST),
(NowX+(LENGTH(Sprites[ORD(UfoST)]) DIV 2)),
NowY+1);
END;
SpriteLen := LENGTH(Sprites[ORD(UfoST)]);
FindXY(UfoST);
IF (NowX = 1) OR ((NowX + SpriteLen) > 79) THEN
BEGIN
SetPosn(UfoST,0,0);
BEEP(3500);
GOTOXY(NowX,NowY);
WRITE(Copy(Blanks,1,SpriteLen));
END;
END; { Ufo Movement }
END; { Ufo Introduction }
END; { MoveUfo }
{======= INITIALIZATION =======}
PROCEDURE StartUp;
VAR
Loop1 : BYTE;
BEGIN
Banner;
CLRSCR;
ActiveCnt := 0;
Beat := 0;
InChar := '?';
Noise := TRUE;
RandomMod := 0;
Score := 0;
ShieldCnt := 0;
ShieldLev := 5;
UfoTick := 0;
FOR Loop1 := 0 TO NumSyms DO
BEGIN
Active[Loop1] := FALSE;
Move[Loop1] := 0;
XPosn[Loop1] := 0;
YPosn[Loop1] := 0;
END;
SetPosn(Base,39,24);
END;
{======= MAINLINE =======}
BEGIN
StartUp;
Cursor(Off);
ShowScore;
REPEAT
IF (Score DIV 1000 > ShieldCnt) AND (ShieldLev < 5)
THEN
BEGIN
ShieldLev := ShieldLev + 1;
ShieldCnt := ShieldCnt + 1;
ShowScore;
END;
{--- Beats and Ticks ---}
Tick := RANDOM(50) + RandomMod;
IF InChar = 'F' THEN RandomMod := RandomMod + 1;
IF RandomMod > 50 THEN RandomMod := 0;
Beat := Beat + 1;
IF Beat > 100 THEN Beat := 0;
{--- Commands ---}
IF KEYPRESSED THEN
BEGIN
BEEP(500);
READ(KBD,InChar);
InChar := UPCASE(InChar);
CASE InChar OF
'-' : BEGIN
Noise := NOT Noise;
NOSOUND;
END;
'F' : Move[ORD(Base)] := -1;
'J' : Move[ORD(Base)] := 1;
'I' : Move[ORD(Base)] := 0;
'E' : Move[ORD(Base)] := 0;
' ' : BEGIN
Score := Score - 1;
IF Score < 0 THEN Score := 0;
IF Active[ORD(Missle)] THEN
BEGIN
FindXY(Missle);
GOTOXY(NowX,NowY);
WRITE(' ');
END;
BEEP(2200);
FindXY(Base);
SetPosn(Missle,NowX+3,23);
END; { SPACE CASE }
'P' : BEGIN
NOSOUND;
GOTOXY(70,1);
WRITE('*PAUSED*');
REPEAT UNTIL KEYPRESSED;
READ(KBD,InChar);
InChar := '?';
GOTOXY(70,1);
WRITE(' ');
END;
END; { CASE }
END;
{--- Timing Delay ---}
DelayTime := DelayInit - ActiveCnt * DelayAdj;
DelayTime := DelayTime - (Score DIV 250);
IF DelayTime < 0 THEN DelayTime := 0;
IF Divis(Beat,10) THEN BEEP(150);
DELAY(DelayTime);
{--- Base Movement ---}
MoveX(Base);
IF (Divis(Beat,2)) AND (Move[ORD(Base)] <> 0)
THEN BEEP(1000+NowX*10)
ELSE NOSOUND;
{--- Weapon Movement ---}
MoveWeapon(Missle);
IF ShieldLev > 0 THEN
BEGIN
{--- Bring in a new UFO? ---}
UfoType := Ufo1;
IF Beat > 10 THEN UfoType := Ufo2;
IF Beat > 25 THEN UfoType := Ufo3;
IF Beat > 50 THEN UfoType := Ufo4;
IF Beat > 75 THEN UfoType := Ufo5;
IF Beat > 90 THEN UfoType := Ufo6;
IF ((RANDOM(1000) <= (Score DIV 100) + 15)
OR (ActiveCnt <= 2))
AND (Active[ORD(UfoType)] = FALSE)
THEN SetPosn(UfoType,1,ORD(UfoType) + RANDOM(5));
MoveWeapon(Bomb1);
MoveUfo(Ufo1);
MoveWeapon(Bomb2);
MoveUfo(Ufo2);
MoveWeapon(Bomb3);
MoveUfo(Ufo3);
MoveWeapon(Bomb4);
MoveUfo(Ufo4);
MoveWeapon(Bomb5);
MoveUfo(Ufo5);
MoveWeapon(Bomb6);
FOR MoveUfo6 := 1 to 5 DO
BEGIN
MoveUfo(Ufo6);
END;
END; { ShieldLev > 0 }
IF ShieldLev <= 0 THEN
BEGIN
CLRSCR;
WRITELN;
WRITELN(' G A M E O V E R -- Score: ',Score);
WRITELN;
IF Noise THEN
BEGIN
FOR Thingy := 4 DOWNTO 1 DO
BEGIN
SOUND(500+Thingy * 1000);
DELAY(500+RANDOM(5-Thingy)*80);
END;
END;
END;
UNTIL (InChar = #27) OR (ShieldLev = 0);
NOSOUND;
Cursor(On);
END.